package com.nl.lib_core.base

import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.ViewStub
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.activity.OnBackPressedDispatcher
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import com.nl.lib_core.R
import com.nl.lib_core.event.core.BaseActivityEvent
import com.nl.lib_core.manager.ActivityManager
import com.nl.lib_core.mvp.IBaseView
import com.nl.lib_core.tool.NetUtil
import com.nl.lib_core.view.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

/** 作者: wangfei 创建时间: 2021/9/1 包名: com.nl.lib_core.base 类名: BaseActivity */
abstract class BaseActivity : AppCompatActivity(), IBaseView {
  // 标题文字
  private var mTxtTitle: TextView? = null

  // 内容布局的父布局 用于设置margin top
  private var mRlContentRoot: FrameLayout? = null

  // 标题栏
  private var mToolbar: Toolbar? = null

  // 解决状态栏与布局顶部重叠问题的高度为0的空view
  private lateinit var mTopView: View

  // 标题栏蓝色图片
  private var mIvHead: ImageView? = null

  private var mNetErrorView: NetErrorView? = null
  private var mNoDataView: NoDataView? = null
  private var mLoadingInitView: LoadingInitView? = null
  private var mAuthorizationView: AuthorizationView? = null
  private var mAppErrorView: AppErrorView? = null
  private var mResultGoWaitView: ResultGoWaitView? = null

  /** activity在跳转的时候显示的页面布局 */
  private lateinit var mViewStubResultGoWait: ViewStub

  // 顶部标题和设置
  private lateinit var mViewStubToolbar: ViewStub

  // 内容布局
  private lateinit var mViewStubContent: ViewStub

  // Loading布局
  private lateinit var mViewStubInitLoading: ViewStub

  // 空数据布局
  private lateinit var mViewStubNoData: ViewStub

  // 错误布局
  private lateinit var mViewStubError: ViewStub

  // 授权布局
  private lateinit var mViewStubAuthor: ViewStub

  // 程序崩溃
  private lateinit var mViewStubAppError: ViewStub

  private var fallbackOnBackPressed: Runnable? = null

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.core_activity_root)
    fixAndroidQMemoryLeak()
    initCommonView()
    initImmersionBar()
    initListener()
    initData()
    ActivityManager.getInstance()?.addActivity(this)
  }

  protected open fun initCommonView() {
    mIvHead = findViewById(R.id.iv_head)
    mTopView = findViewById(R.id.top_view)
    mViewStubContent = findViewById(R.id.view_stub_content)
    mViewStubInitLoading = findViewById(R.id.view_stub_init_loading)
    mViewStubError = findViewById(R.id.view_stub_error)
    mViewStubNoData = findViewById(R.id.view_stub_nodata)
    mViewStubAuthor = findViewById(R.id.view_stub_author)
    mViewStubAppError = findViewById(R.id.view_stub_app_error)
    mViewStubToolbar = findViewById(R.id.view_stub_toolbar)
    mRlContentRoot = findViewById(R.id.rl_content_root)
    mViewStubResultGoWait = findViewById(R.id.view_stub_app_go_wait)
    if (enableToolbar()) {
      mViewStubToolbar.layoutResource = onBindToolbarLayout()
      val view = mViewStubToolbar.inflate()
      initToolbar(view)
    }
    val onBindLayoutId = onBindLayout()
    if (onBindLayoutId != -1) {
      mViewStubContent.layoutResource = onBindLayoutId
      mViewStubContent.inflate()
    }
  }

  private fun initToolbar(view: View) {
    mToolbar = view.findViewById(R.id.toolbar_root)
    mTxtTitle = view.findViewById(R.id.toolbar_title)
    mToolbar?.let {
      setSupportActionBar(it)
      supportActionBar!!.setDisplayShowTitleEnabled(false)
      it.setNavigationOnClickListener { onBackPressed() }
    }
  }

  /** 替换标题文字 */
  override fun onTitleChanged(title: CharSequence, color: Int) {
    super.onTitleChanged(title, color)
    if (title.isNotBlank()) {
      mTxtTitle?.text = title
    }
    // 可以再次覆盖设置title
    val tootBarTitle = getTootBarTitle()
    if (tootBarTitle.isNotBlank()) {
      mTxtTitle?.text = tootBarTitle
    }
  }

  /** 当前栏目栏的中文标题 */
  open fun getTootBarTitle(): String {
    return ""
  }

  /** 绑定的栏目栏的资源id */
  open fun onBindToolbarLayout(): Int {
    return R.layout.core_common_toolbar
  }

  /** 退出当前App */
  override fun onDestroy() {
    super.onDestroy()
    EventBus.getDefault().unregister(this)
    ActivityManager.getInstance()?.finishActivity(this)
  }

  override fun initListener() {}

  override fun finishActivity() {
    finish()
  }

  /** 设置是否显示栏目栏 可以通过覆盖来关闭栏目栏 */
  open fun enableToolbar(): Boolean {
    return true
  }

  override fun showInitLoadView() {
    whetherShowInitLoadView(true)
  }

  override fun hideInitLoadView() {
    whetherShowInitLoadView(false)
  }

  override fun showNoDataView() {
    whetherShowNoDataView(true)
  }

  override fun showNoDataView(resId: Int) {
    showNoDataView(true, resId)
  }

  override fun hideNoDataView() {
    whetherShowNoDataView(false)
  }

  override fun hideNetWorkErrView() {
    whetherShowNetWorkErrView(false)
  }

  override fun showNetWorkErrView() {
    whetherShowNetWorkErrView(true)
  }

  override fun showAuthorView() {
    whetherShowAuthorView(true)
  }

  override fun hideAuthorView() {
    whetherShowAuthorView(false)
  }

  override fun showAppErrorView() {
    whetherAppErrorView(true)
  }

  override fun hideAppErrorView() {
    whetherAppErrorView(false)
  }

  fun showResultGoView() {
    whetherShowResultGoView(true)
  }

  fun hideResultGoView() {
    whetherShowResultGoView(false)
  }

  /** 展示和隐藏加载中 */
  private fun whetherShowInitLoadView(show: Boolean) {
    if (mLoadingInitView == null) {
      val view = mViewStubInitLoading.inflate()
      mLoadingInitView = view.findViewById(R.id.view_init_loading)
    }
    mLoadingInitView?.visibility = if (show) View.VISIBLE else View.GONE
  }

  /** 展示网络错误 带刷新功能 */
  private fun whetherShowNetWorkErrView(show: Boolean) {
    if (mNetErrorView == null) {
      val view = mViewStubError.inflate()
      mNetErrorView = view.findViewById(R.id.view_net_error)
      mNetErrorView?.setRefreshBtnClickListener {
        if (NetUtil.checkNetToast()) {
          reFreshRequest()
        }
      }
    }
    // 单机模式关闭 或 有网的情况下隐藏单机按钮
    if (NetUtil.checkNet()) {
      mNetErrorView?.hideCheckToLocalBTN()
    } else {
      mNetErrorView?.showCheckToLocalBTN()
    }
    mNetErrorView?.visibility = if (show) View.VISIBLE else View.GONE
  }

  /** 展示空数据布局 */
  private fun whetherShowNoDataView(show: Boolean) {
    if (mNoDataView == null) {
      val view = mViewStubNoData.inflate()
      mNoDataView = view.findViewById(R.id.view_no_data)
    }
    mNoDataView?.visibility = if (show) View.VISIBLE else View.GONE
  }

  private fun showNoDataView(show: Boolean, resId: Int) {
    whetherShowNoDataView(show)
    if (show) {
      mNoDataView?.setNoDataView(resId)
    }
  }

  /** 展示没有授权的页面 */
  private fun whetherShowAuthorView(show: Boolean) {
    if (mAuthorizationView == null) {
      val view = mViewStubAuthor.inflate()
      mAuthorizationView = view.findViewById(R.id.view_init_author)
      mAuthorizationView?.setRefreshBtnClickListener {
        if (NetUtil.checkNetToast()) {
          reFreshRequest()
        }
      }
    }
    mAuthorizationView?.visibility = if (show) View.VISIBLE else View.GONE
  }

  private fun whetherAppErrorView(show: Boolean) {
    if (mAppErrorView == null) {
      val view = mViewStubAppError.inflate()
      mAppErrorView = view.findViewById(R.id.view_init_app_error)
      mAppErrorView?.setRefreshBtnClickListener { goToDesignatePage() }
    }
    mAppErrorView?.visibility = if (show) View.VISIBLE else View.GONE
  }

  private fun whetherShowResultGoView(show: Boolean) {
    if (mResultGoWaitView == null) {
      val view = mViewStubResultGoWait.inflate()
      mResultGoWaitView = view.findViewById(R.id.view_init_result_go_wait)
    }
    mResultGoWaitView?.visibility = if (show) View.VISIBLE else View.GONE
  }

  /** eventBus接受源 */
  @Subscribe(threadMode = ThreadMode.MAIN)
  public open fun <T> onEvent(event: BaseActivityEvent<T>) {}

  /** 用于点击刷新网络请求接口 */
  open fun reFreshRequest() {}

  /** 跳转到指定页面 */
  open fun goToDesignatePage() {}

  abstract fun onBindLayout(): Int

  abstract override fun initData()

  /** 初始化沉浸式 */
  abstract fun initImmersionBar()

  companion object {
    val TAG = BaseActivity::class.java.simpleName
    val fallbackOnBackPressedField by lazy {
      if (Build.VERSION.SDK_INT != Build.VERSION_CODES.Q) {
        null
      } else {
        // OnBackPressedDispatcher 中只有fallbackOnBackPressed是Runnable
        // 这样可以避免代码混淆带来的影响
        OnBackPressedDispatcher::class.java.declaredFields.find {
          it.type.isAssignableFrom(Runnable::class.java)
        }
      }
    }
  }

  /** 修复AndroidQ 系统bug 内存泄漏 */
  private fun fixAndroidQMemoryLeak() {
    if (Build.VERSION.SDK_INT != Build.VERSION_CODES.Q) return
    fallbackOnBackPressedField
        ?.runCatching {
          isAccessible = true
          // 缓存默认的 fallbackOnBackPressed，如果不是TaskRoot还可以直接用它
          fallbackOnBackPressed = get(onBackPressedDispatcher) as? Runnable
          if (fallbackOnBackPressed != null) {
            // 替换默认的 fallbackOnBackPressed
            set(onBackPressedDispatcher, Runnable { onFallbackOnBackPressed() })
          }
          fallbackOnBackPressedField?.isAccessible = false
        }
        ?.onFailure { fallbackOnBackPressedField?.isAccessible = false }
  }

  /**
   * FragmentActivity等都是利用[mOnBackPressedDispatcher]addCallback完成Fragment pop， 并且会优先于
   * [OnBackPressedDispatcher]#mFallbackOnBackPressed执行
   */
  @RequiresApi(Build.VERSION_CODES.Q)
  private fun onFallbackOnBackPressed() {
    // 如果不是TaskRoot，不存在内存泄漏，执行原有函数就可以
    if (!isTaskRoot) {
      fallbackOnBackPressed?.run()
      return
    }
    // actionBar#collapseActionView 属于私有函数，所以就不要在Activity中使用[android.app.ActionBar]
    // if (actionBar != null && actionBar.collapseActionView()) return
    if (!fragmentManager.isStateSaved && fragmentManager.popBackStackImmediate()) return
    finishAfterTransition()
  }
}
